#pragma once

#include "Vector.h"
#include "Mesh.h"
#include "VertexAttribute.h"
#include "Utils.h"
#include "RectangleD.h"


namespace Core
{
	class RectangleTessellator
	{
	public:
		static Mesh* Compute(const RectangleD& rectangle, int numberOfPartitionsX, int numberOfPartitionsY)
		{
			if (numberOfPartitionsX < 0 || numberOfPartitionsY < 0)
			{
				assert(false);
			}

			Mesh* mesh = new Mesh();

			mesh->SetPrimitiveType(PrimitiveType::Triangles);
			mesh->SetFrontFaceWindingOrder(WindingOrder::Counterclockwise);
			

			int numberOfPositions = (numberOfPartitionsX + 1) * (numberOfPartitionsY + 1);
			VertexAttributeFloatVector2* positionsAttribute = new VertexAttributeFloatVector2("position");
			std::vector<Vector2F>* positions = positionsAttribute->GetValues();
			mesh->GetAttributes()->Add(positionsAttribute);

			int numberOfIndices = (numberOfPartitionsX * numberOfPartitionsY) * 6;
			IndicesUnsignedInt* indices = new IndicesUnsignedInt();
			mesh->SetIndices(indices);


			Vector2D lowerLeft = rectangle.GetLowerLeft();
			Vector2D toUpperRight = rectangle.GetUpperRight() - lowerLeft;
			
			for (int y = 0; y <= numberOfPartitionsY; ++y)
			{
				double deltaY = y / (double)numberOfPartitionsY;
				double currentY = lowerLeft.y + (deltaY * toUpperRight.y);

				for (int x = 0; x <= numberOfPartitionsX; ++x)
				{
					double deltaX = x / (double)numberOfPartitionsX;
					double currentX = lowerLeft.x + (deltaX * toUpperRight.x);
					positions->push_back(Vector2F(currentX, currentY));
				}
			}
			
			
			int rowDelta = numberOfPartitionsX + 1;
			int i = 0;
			for (int y = 0; y < numberOfPartitionsY; ++y)
			{
				for (int x = 0; x < numberOfPartitionsX; ++x)
				{
					indices->AddTriangle(TriangleIndicesUnsignedInt(i, i + 1, rowDelta + (i + 1)));
					indices->AddTriangle(TriangleIndicesUnsignedInt(i, rowDelta + (i + 1), rowDelta + i));
					i += 1;
				}
				i += 1;
			}

			return mesh;
		}
	};
}